package com.gzhryc.shared_device.oem.code.place.services;

import com.gzhryc.common.StringTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.JdbcSession;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.oem.code.agent.dao.db.AgentRelation;
import com.gzhryc.shared_device.oem.code.agent.dao.enums.AgentRelationEnum;
import com.gzhryc.shared_device.oem.code.agent.services.AgentRelationService;
import com.gzhryc.shared_device.oem.code.business.EBusinessType;
import com.gzhryc.shared_device.oem.code.place.dao.db.PlaceBusinessConfig;
import com.gzhryc.shared_device.oem.code.place.dao.db.PlacePhysicalStore;
import com.gzhryc.shared_device.oem.code.place.dao.models.IncomeRatioContent;
import com.gzhryc.shared_device.oem.code.place.dao.models.PlaceUserCount;
import com.gzhryc.shared_device.oem.code.place.dao.models.RoleTypePlaceCount;
import com.gzhryc.shared_device.oem.code.place.dao.models.UserProfitPlaceCount;
import com.gzhryc.shared_device.oem.code.user.ERoleType;
import com.gzhryc.shared_device.oem.code.user.dao.db.User;
import com.gzhryc.shared_device.oem.code.user.services.UserService;
import com.gzhryc.shared_device.oem.code.place.dao.PlaceProfitUserDao;
import com.gzhryc.shared_device.oem.code.place.dao.db.PlaceProfitUser;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PlaceProfitUserService {

    static Logger log = Logger.getLogger(PlaceProfitUserService.class);

    public static PlaceProfitUserService self() {
        return MultiDBTools.getService(PlaceProfitUserService.class, true);
    }

    public static PlaceProfitUserService self(String jdbcKey) {
        return MultiDBTools.getService(jdbcKey, PlaceProfitUserService.class, true);
    }

    PlaceProfitUserDao dao;

    public PlaceProfitUserService(String jdbcKey) {
        this.dao = new PlaceProfitUserDao(jdbcKey);
    }

    public List<PlaceProfitUser> findByPlaceId(Long placeId) {
        if (placeId != null) {
            Conditions conditions = new Conditions(PlaceProfitUser.class);
            conditions.and().is("placeId", placeId);

            try {
                return dao.findByCondition(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public List<PlaceProfitUser> findJoinByPlaceId(Long placeId) {
        if (placeId != null) {
            Conditions conditions = new Conditions(PlaceProfitUser.class);
            conditions.and().is("placeId", placeId);

            try {
                return dao.findJoinByCondition(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public Long countByUserId(Long userId){
        if (userId != null) {
            Conditions conditions = new Conditions(PlaceProfitUser.class);
            conditions.and().is("userId", userId);

            try {
                return dao.count(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return 0L;
    }

    public Long countByUserKeys(Long placeUserId,Long userId){
        if (placeUserId != null && userId != null) {
            Conditions conditions = new Conditions(PlaceProfitUser.class);
            conditions.and().is("placeUserId", placeUserId);
            conditions.and().is("userId", userId);

            try {
                return dao.count(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return 0L;
    }

    public List<PlaceProfitUser> findByUserId(Long userId,Integer pageNo,Integer pageLimit){
        if (userId != null) {
            Conditions conditions = new Conditions(PlaceProfitUser.class);
            conditions.and().is("userId", userId);

            try {
                return dao.findByCondition(conditions,pageNo,pageLimit);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public List<PlaceProfitUser> findByPlaceUserId(Long placeUserId){
        if (placeUserId != null) {
            Conditions conditions = new Conditions(PlaceProfitUser.class);
            conditions.and().is("placeUserId", placeUserId);

            try {
                return dao.findByCondition(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public List<PlaceProfitUser> findByUserKeys(Long placeUserId,Long userId){
        if (placeUserId != null && userId != null) {
            Conditions conditions = new Conditions(PlaceProfitUser.class);
            conditions.and().is("placeUserId", placeUserId);
            conditions.and().is("userId",userId);

            try {
                return dao.findByCondition(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public List<UserProfitPlaceCount> findPlaceCountByUserKeys(Long placeUserId,List<Long> userIds){
        if(placeUserId != null && userIds != null && userIds.size() > 0){
            Conditions conditions = new Conditions(PlaceProfitUser.class);
            conditions.and().is("placeUserId", placeUserId);
            conditions.and().in("userId",userIds);

            try {
                return dao.countGroupUserId(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }
    
    public List<RoleTypePlaceCount> findRolePlaceCountByUserKeys(Long placeUserId,Long userId){
        if(placeUserId != null && userId != null){
            Conditions conditions = new Conditions(PlaceProfitUser.class);
            conditions.and().is("placeUserId", placeUserId);
            conditions.and().is("userId",userId);

            try {
                return dao.countGroupRoleType(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public List<PlaceUserCount> findUserCountByPlaceId(List<Long> placeIds){
        if(placeIds != null && placeIds.size() > 0){
            Conditions conditions = new Conditions(PlaceProfitUser.class);
            conditions.and().in("placeId", placeIds);

            try {
                return dao.countGroupPlaceId(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public PlaceProfitUser getByKeys(Long placeId, Long userId) {
        if (placeId != null && userId != null) {
            Conditions conditions = new Conditions(PlaceProfitUser.class);
            conditions.and().is("placeId", placeId);
            conditions.and().is("userId", userId);

            try {
                return dao.get(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public PlaceProfitUser getJoinByKeys(Long placeId, Long userId) {
        if (placeId != null && userId != null) {
            Conditions conditions = new Conditions(PlaceProfitUser.class);
            conditions.and().is("placeId", placeId);
            conditions.and().is("userId", userId);

            try {
                return dao.getJoin(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }
    
    public PlaceProfitUser getPartnerByPlaceId(Long placeId) {
    	if(placeId != null) {
    		Conditions conditions = new Conditions(PlaceProfitUser.class);
    		conditions.and().is("placeId", placeId);
    		conditions.and().is("type", ERoleType.Partner.index());
    		
    		try {
				return dao.get(conditions);
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
    	}	
    	return null;
    }

    public boolean add(PlacePhysicalStore physicalStore,PlaceProfitUser placeProfitUser,User user, IncomeRatioContent incomeRatioContent
    		,OperateInfo operateInfo) throws LogicException {
        if (physicalStore == null) {
            throw new LogicException("未找到网点信息");
        }
        
        if(ERoleType.Partner.index().equals(placeProfitUser.getRoleType())) {
        	//一个网点只能存在一个合伙人
        	PlaceProfitUser temp = getPartnerByPlaceId(physicalStore.getId());
        	if(temp != null) {
        		throw new LogicException("一个网点只能有一个合伙人");
        	}
        }
       
        if (incomeRatioContent != null) {
            List<PlaceProfitUser> tempList = findByPlaceId(placeProfitUser.getPlaceId());
            Map<String, Double> incomeRatioMap = new HashMap<>();
            if (tempList != null && tempList.size() > 0) {
                for (PlaceProfitUser temp : tempList) {
                    if (StringTools.isNotBlank(temp.getIncomeRatioContent())) {
                        IncomeRatioContent tempIncomeRatio = JsonTools.fromJson(temp.getIncomeRatioContent(), IncomeRatioContent.class);
                        for (IncomeRatioContent.Item item : tempIncomeRatio.getItems()) {
                            Double incomeRatio = incomeRatioMap.get(item.getBusinessType());
                            if (incomeRatio == null) {
                                incomeRatio = 0.0;
                            }
                            incomeRatio = incomeRatio + item.getIncomeRatio();
                            incomeRatioMap.put(item.getBusinessType(), incomeRatio);
                        }
                    }
                }
            }

            for (IncomeRatioContent.Item item : incomeRatioContent.getItems()) {
                Double incomeRatio = incomeRatioMap.get(item.getBusinessType());
                if (incomeRatio == null) {
                    incomeRatio = 0.0;
                }
                incomeRatio = incomeRatio + item.getIncomeRatio();
                if (incomeRatio > 100D) {
                    throw new LogicException(EBusinessType.note(item.getBusinessType()) + "分成比例超过100%");
                }
            }

            placeProfitUser.setIncomeRatioContent(JsonTools.toJson(incomeRatioContent));
        }

        if (user.getId() == null) {
            User temp = UserService.self().getByPhone(user.getPhone());
            if (temp != null) {
                user.setId(temp.getId());
            }
        }

        if (user.getId() != null) {
            if (physicalStore.getUserId().equals(user.getId())) {
                throw new LogicException("用户是网点的代理");
            }

            if (getByKeys(placeProfitUser.getPlaceId(), user.getId()) != null) {
                throw new LogicException("网点已存在该用户的分成比例");
            }
        }

        placeProfitUser.setPlaceUserId(physicalStore.getUserId());
        placeProfitUser.setCreateDate(new Date());

        JdbcSession.begin();
        try {
            if (user.getId() == null) {
                if (!UserService.self().add(user)) {
                    throw new LogicException("新增用户失败");
                }
            }

            placeProfitUser.setUserId(user.getId());
            if (dao.insert(placeProfitUser) > 0) {
                AgentRelation agentRelation = AgentRelationService.self().getByKeys(physicalStore.getUserId(),placeProfitUser.getUserId());
                if(agentRelation == null) {
                    agentRelation = new AgentRelation();
                    agentRelation.setUserId(physicalStore.getUserId());
                    agentRelation.setRelationUserId(user.getId());
                    if(ERoleType.Partner.index().equals(placeProfitUser.getRoleType())) {
                    	agentRelation.setRoleType(AgentRelationEnum.RoleType.Partner.index());
                    }else {
                    	agentRelation.setRoleType(AgentRelationEnum.RoleType.Dealer.index());
                    }
                    if (!AgentRelationService.self().add(agentRelation,null)) {
                        throw new LogicException("保存用户关系失败");
                    }
                }
                
                //记录日志
                PlaceLogsRecordService.self().byUserAdd(physicalStore, placeProfitUser, operateInfo);
                
                JdbcSession.commit();
                return true;
            }
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        } finally {
            JdbcSession.end();
        }
        return false;   //结束
    }

    public boolean updateNotNull(PlaceProfitUser placeProfitUser, IncomeRatioContent incomeRatioContent) throws LogicException{
        if(placeProfitUser.getPlaceId() != null && placeProfitUser.getUserId() != null){
            PlaceProfitUser temp = getByKeys(placeProfitUser.getPlaceId(),placeProfitUser.getUserId());
            if(temp == null){
                throw new LogicException("未找到网点用户信息");
            }
            
            //检查网点业务类型
            List<PlaceBusinessConfig> placeBusinessConfigList = PlaceBusinessConfigService.self().findByPlaceId(placeProfitUser.getPlaceId());
            
            if(placeBusinessConfigList == null || placeBusinessConfigList.size() == 0){
            	placeProfitUser.setIncomeRatioContent(null);
            }else {
	            //检查
	            if(incomeRatioContent != null){
	                List<PlaceProfitUser> tempList = findByPlaceId(placeProfitUser.getPlaceId());
	                Map<String, Double> incomeRatioMap = new HashMap<>();
	                if (tempList != null && tempList.size() > 0) {
	                    for (PlaceProfitUser user : tempList) {
	                        //不记录自身
	                        if (!user.getUserId().equals(placeProfitUser.getUserId()) && StringTools.isNotBlank(user.getIncomeRatioContent())) {
	                            IncomeRatioContent tempIncomeRatio = JsonTools.fromJson(user.getIncomeRatioContent(), IncomeRatioContent.class);
	                            for (IncomeRatioContent.Item item : tempIncomeRatio.getItems()) {
	                                Double incomeRatio = incomeRatioMap.get(item.getBusinessType());
	                                if (incomeRatio == null) {
	                                    incomeRatio = 0.0;
	                                }
	                                incomeRatio = incomeRatio + item.getIncomeRatio();
	                                incomeRatioMap.put(item.getBusinessType(), incomeRatio);
	                            }
	                        }
	                    }
	                }
	                
	                if(placeBusinessConfigList != null) {
		                List<IncomeRatioContent.Item> itemList = new ArrayList<IncomeRatioContent.Item>();
		                for(IncomeRatioContent.Item item : incomeRatioContent.getItems()){
		                	for(PlaceBusinessConfig businessConfig : placeBusinessConfigList){
		                		if(businessConfig.getBusinessType().equals(item.getBusinessType())) {
		                			itemList.add(item);
		                			break;
		                		}
		                	}
		                }
		                incomeRatioContent.setItems(itemList);
		                
		                for(IncomeRatioContent.Item item : incomeRatioContent.getItems()){
		                    Double incomeRatio = incomeRatioMap.get(item.getBusinessType());
		                    if (incomeRatio == null) {
		                        incomeRatio = 0.0;
		                    }
		                    incomeRatio = incomeRatio + item.getIncomeRatio();
		                    if(incomeRatio > 100D){
		                        throw new LogicException(EBusinessType.note(item.getBusinessType()) + "分成比例超过100%");
		                    }
		                }
		                placeProfitUser.setIncomeRatioContent(JsonTools.toJson(incomeRatioContent));
	                }
	            }
            }

            Conditions conditions = new Conditions(PlaceProfitUser.class);
            conditions.and().is("placeId",placeProfitUser.getPlaceId());
            conditions.and().is("userId",placeProfitUser.getUserId());

            try {
                return dao.updateNotNull(placeProfitUser,conditions,"note","incomeRatioContent") > 0;
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return false;
    }

    public boolean deleteBusinessTypeIncomeRatio(Long placeId,Long userId,String businessType) throws LogicException{
        PlaceProfitUser profitUser = PlaceProfitUserService.self().getByKeys(placeId, userId);
        if (StringTools.isNotBlank(profitUser.getIncomeRatioContent())) {
            IncomeRatioContent incomeRatioContent = JsonTools.fromJson(profitUser.getIncomeRatioContent(), IncomeRatioContent.class);
            int index = -1;
            for (int i = 0; i < incomeRatioContent.getItems().size(); i++) {
                IncomeRatioContent.Item item = incomeRatioContent.getItems().get(i);
                if (item.getBusinessType().equals(businessType)) {
                    index = i;
                    break;
                }
            }

            if (index >= 0) {
                incomeRatioContent.getItems().remove(index);

                Conditions conditions = new Conditions(PlaceProfitUser.class);
                conditions.and().is("placeId", placeId);
                conditions.and().is("userId", userId);

                Map<String, Object> data = new HashMap<>();

                if (incomeRatioContent.getItems().size() > 0) {
                    data.put("incomeRatioContent", JsonTools.toJson(incomeRatioContent));
                } else {
                    data.put("incomeRatioContent", null);
                }

                try {
                    return dao.update(data, conditions) > 0;
                } catch (SQLException e) {
                    log.error(e.getMessage(), e);
                }
            }else{
                throw new LogicException("未找到网点用户的" + EBusinessType.note(businessType) + "分成");
            }
        }
        return false;
    }

    public boolean deleteByPlaceId(Long placeId){
        if (placeId != null) {
            Conditions conditions = new Conditions(PlaceProfitUser.class);
            conditions.and().is("placeId", placeId);

            try {
                return dao.deleteByCondition(conditions) >= 0;
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return false;
    }

    public boolean deleteByKeys(Long placeId,Long userId) throws LogicException{
        if(placeId != null && userId != null){
            PlacePhysicalStore physicalStore = PlacePhysicalStoreService.self().getById(placeId);
            if(physicalStore == null){
                throw new LogicException("网点不存在");
            }
            Conditions conditions = new Conditions(PlaceProfitUser.class);
            conditions.and().is("placeId",placeId);
            conditions.and().is("userId",userId);

            JdbcSession.begin();
            try {
                if(dao.deleteByCondition(conditions) > 0){
                    JdbcSession.commit();
                    return true;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            } finally {
                JdbcSession.end();
            }
        }
        return false;
    }
}
